﻿namespace lpr
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;

    internal sealed class ProcessorImpl : IProcessor, IDisposable
    {
        private IntPtr _hEng;
        private IntPtr _hProc;
        private Shimmy _shim;

        public ProcessorImpl(Shimmy shim, IntPtr hEng, IntPtr hProc)
        {
            this._shim = shim;
            this._hEng = hEng;
            this._hProc = hProc;
        }

        public List<Candidate> analyze(string imgPath, uint maxCharHeight)
        {
            List<Candidate> cds = new List<Candidate>();
            IntPtr hCds = this._shim.Processor_analyzeFile(this._hProc, imgPath, maxCharHeight);
            this.check(hCds != IntPtr.Zero);
            this.cvt(hCds, cds);
            this._shim.ReferenceCounted_release(hCds);
            return cds;
        }

        public List<Candidate> analyze(IntPtr pImgData, uint widthStep, uint width, uint height, uint maxCharHeight)
        {
            List<Candidate> cds = new List<Candidate>();
            IntPtr hCds = this._shim.Processor_analyzeBuffer(this._hProc, pImgData, widthStep, width, height, maxCharHeight);
            this.check(hCds != IntPtr.Zero);
            this.cvt(hCds, cds);
            this._shim.ReferenceCounted_release(hCds);
            return cds;
        }

        private void check(bool bResult)
        {
            if (!bResult)
            {
                this.throwIfError();
            }
        }

        private void cleanup()
        {
            if (this._hProc != IntPtr.Zero)
            {
                this._shim.ReferenceCounted_release(this._hProc);
                this._hProc = IntPtr.Zero;
            }
        }

        private void cvt(IntPtr hCds, List<Candidate> cds)
        {
            uint num = this._shim.Candidates_numCandidates_get(hCds);
            for (uint i = 0; i < num; i++)
            {
                Candidate candidate;
                IntPtr hCandidate = this._shim.Candidates_candidate_get(hCds, i);
                candidate.text = this._shim.Candidate_text_get(hCandidate);
                candidate.country = this._shim.Candidate_country_get(hCandidate);
                candidate.confidence = this._shim.Candidate_confidence_get(hCandidate);
                candidate.brightBackground = this._shim.Candidate_brightBackground_get(hCandidate) > 0;
                candidate.elements = new List<Element>();
                uint num3 = this._shim.Candidate_numElements_get(hCandidate);
                for (uint j = 0; j < num3; j++)
                {
                    Shimmy.SIMPLELPR_Element element;
                    Element element2;
                    this._shim.Candidate_element_get(hCandidate, j, out element);
                    element2.glyph = element.glyph;
                    element2.confidence = element.fConfidence;
                    element2.bbox = new Rectangle();
                    element2.bbox.X = element.boundingBox.left;
                    element2.bbox.Y = element.boundingBox.top;
                    element2.bbox.Width = element.boundingBox.width;
                    element2.bbox.Height = element.boundingBox.height;
                    candidate.elements.Add(element2);
                }
                this._shim.ReferenceCounted_release(hCandidate);
                cds.Add(candidate);
            }
        }

        public void Dispose()
        {
            this.cleanup();
            GC.SuppressFinalize(this);
        }

        ~ProcessorImpl()
        {
            this.cleanup();
        }

        private void throwIfError()
        {
            IntPtr hErrInfo = this._shim.lastError_get(this._hEng, 1);
            if (hErrInfo != IntPtr.Zero)
            {
                Exception exception = new Exception(this._shim.ErrorInfo_description_get(hErrInfo));
                this._shim.ReferenceCounted_release(hErrInfo);
                throw exception;
            }
        }
    }
}

